#include "MainGameState.h"
#include "AntTweakBar.h"
#include "EventPoller.h"
#include "Timer.h"
#include <time.h>
#include "OBJManager.h"
#include "TextureManager.h"
#include "SeekPoIState.h"
#include "ShaderManager.h"
#include "ObjUsefulFunctions.h"
#include "ReportError.h"
#include "Game.h"
#include <SDL.h>

#include <glut.h>

MainGameState::MainGameState()
{	
	srand(time(NULL));
	m_LeftMouse = false;
	TheShaderManager::Instance()->LoadShader("Assets/Shaders/VertexShader.vert", "Assets/Shaders/FragmentShader.frag", "Test");
}

void MainGameState::OnActivated()
{
#ifndef _DEBUG
	LoadAssets();
#endif
	LoadAgents();
	//m_Graph = m_AiAgentVec[1].ReturnGraph();
	TheEventPoller::Instance()->AddHandler(this);
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_COLOR_MATERIAL);
	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
	glShadeModel (GL_SMOOTH);
	m_CameraDistance = 10;

	m_LightPosition[0] = 0;
	m_LightPosition[1] = -20;
	m_LightPosition[2] = 0;
	m_LightPosition[3] = 0.0f;

	m_CameraAngle = 0;
	m_CameraPos.m_z = 50;
	m_CameraPos.m_y = 2.5;
	m_CameraIndex = 0;

	m_ShowAiGraph = false;

	TheTweakBar::Instance()->AddVar("Light Direction", TW_TYPE_DIR3F, &m_LightPosition, "");
	TheTweakBar::Instance()->AddVar("Camera Distance", TW_TYPE_FLOAT, &m_CameraDistance, "min=3 max=100");
	TheTweakBar::Instance()->AddVar("Current Agent", TW_TYPE_INT32, &m_CameraIndex, "min=0");
	TheTweakBar::Instance()->AddVar("ShowAiGraph", TW_TYPE_BOOLCPP, &m_ShowAiGraph, "");

	TheTweakBar::Instance()->AddButton("Agent Info", NULL, NULL, "");
	TheTweakBar::Instance()->AddButton("0 = Farmer", NULL, NULL, "");
	TheTweakBar::Instance()->AddButton("1 = Priest", NULL, NULL, "");
	TheTweakBar::Instance()->AddButton("2 = Blacksmith", NULL, NULL, "");

}

void MainGameState::Update()
{
	Controls();
	for(auto it = m_AiAgentVec.begin(); it != m_AiAgentVec.end(); ++it)
	{
		it->Update();
	}
	m_CameraPos.m_x = cos(m_CameraAngle) * m_CameraDistance;
	m_CameraPos.m_z = sin(m_CameraAngle) * m_CameraDistance;
}

void MainGameState::Draw()
{
	glClearColor(0.25, 0.76, 1, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glLightfv(GL_LIGHT0, GL_POSITION, m_LightPosition);
	gluPerspective(45, 1.9, 1, 1000);
	

	if(m_CameraIndex >= m_AiAgentVec.size())
	{
		m_CameraIndex = m_AiAgentVec.size()-1;
	}

	gluLookAt(m_AiAgentVec[m_CameraIndex].ReturnPos().m_x + m_CameraPos.m_x, m_AiAgentVec[m_CameraIndex].ReturnPos().m_y + m_CameraPos.m_y, m_AiAgentVec[m_CameraIndex].ReturnPos().m_z + m_CameraPos.m_z, 
		m_AiAgentVec[m_CameraIndex].ReturnPos().m_x, m_AiAgentVec[m_CameraIndex].ReturnPos().m_y, m_AiAgentVec[m_CameraIndex].ReturnPos().m_z, 
		0, 1, 0);

	for(auto it = m_AiAgentVec.begin(); it != m_AiAgentVec.end(); ++it)
	{
		it->Draw();
	}

	glPushMatrix();
		for(int i = 0; i < m_MeshVec.size(); i++)
		{
			m_MeshVec[i].Draw();
		}
	glPopMatrix();
	
	if(m_ShowAiGraph)
	{
		m_AiAgentVec[m_CameraIndex].ReturnGraph()->DrawWithPath(m_AiAgentVec[m_CameraIndex].ReturnPath());
	}

	//Draw Static Agent Dummys
	
	//Food Stall
	glPushMatrix();
		glTranslatef(34, 1, 25);
		glRotatef(180, 0, 1, 0);
		glutSolidTeapot(1);
	glPopMatrix();

	//Blacksmith Stall
	glPushMatrix();
		glTranslatef(-28, 1, 13);
		glutSolidTeapot(1);
	glPopMatrix();

	//Wizard Stall
	glPushMatrix();
		glTranslatef(-21, 1, -24);
		glutSolidTeapot(1);
	glPopMatrix();

	//Wood Stall
	glPushMatrix();
		glTranslatef(32, 1, -26);
		glRotatef(180, 0, 1, 0);
		glutSolidTeapot(1);
	glPopMatrix();

}

bool MainGameState::LoadAgents()
{
	File file;
	if(!file.OpenRead("Assets/Agents.txt"))
	{
		ReportError("Could Not Open Assets/Agents.txt");
		return false;
	}
	std::string line;
	int NumAgents = 0;
	file.GetInteger(&NumAgents);

	for(int i = 0; i < NumAgents; i++)
	{
		int id = 0;
		std::string prof;
		std::string graphstr;
		std::string positionstr;
		Vec3f Position;
		file.GetInteger(&id);
		file.GetString(&prof);
		file.GetString(&graphstr);
		file.GetString(&positionstr);
		Strings str = Split(positionstr, ' ');
		Position.m_x = ToFloat(str[0]);
		Position.m_y = ToFloat(str[1]);
		Position.m_z = ToFloat(str[2]);

		AiAgent tempagent(Position, id, prof);
		tempagent.LoadGrapthAndPoi(graphstr);
		tempagent.SetAiState(new SeekPoIState);
		m_AiAgentVec.push_back(tempagent);
	}
	return true;
}

void MainGameState::LoadAssets()
{
	File file;
	if(!file.OpenRead("Assets/AssetList.txt"))
	{
		ReportError("Could Not Open Assets/AssetList.txt");
	}

	std::string line;
	while (file.GetString(&line))
	{
		OBJMesh tempmesh;
		tempmesh.Load(line);
		m_MeshVec.push_back(tempmesh);
	}
}


void MainGameState::Controls()
{
		
}

void MainGameState::OnKeyboardEvent(const SDL_KeyboardEvent& Event)
{
	if(Event.type == SDL_KEYDOWN)
	{
		switch(Event.keysym.sym)
		{
		case SDLK_w:
			m_W = true;
			break;
		case SDLK_s:
			m_S = true;
			break;
		case SDLK_1:
			if(m_CameraIndex > 0) m_CameraIndex--;
			break;
		case SDLK_2:
			m_CameraIndex++;
			break;
		case SDLK_SPACE:
			m_ShowAiGraph = !m_ShowAiGraph;
			break;
		default:
			break;
		}
	}
	else if(Event.type == SDL_KEYUP)
	{
		switch(Event.keysym.sym)
		{
		case SDLK_w:
			m_W = false;
			break;
		case SDLK_s:
			m_S = false;
			break;
		default:
			break;
		}
	}
}

void MainGameState::OnMouseMotionEvent(const SDL_MouseMotionEvent& event)
{
	if(m_LeftMouse)
	{
		float dt = TheTimer::Instance()->GetDeltaTime();
		m_CameraAngle += (event.xrel * dt);
		m_CameraPos.m_y += (event.yrel * dt);
	}
}

void MainGameState::OnMouseButtonDownEvent(const SDL_MouseButtonEvent& event)
{
	float dt = TheTimer::Instance()->GetDeltaTime();
	if(event.button == SDL_BUTTON_LEFT)
	{
		m_LeftMouse = true;
	}
	else if(event.button == SDL_BUTTON_WHEELDOWN)
	{
		m_CameraDistance += 40 * dt;
	}
}

void MainGameState::OnMouseButtonUpEvent(const SDL_MouseButtonEvent& event)
{
	float dt = TheTimer::Instance()->GetDeltaTime();
	if(event.button == SDL_BUTTON_LEFT)
	{
		m_LeftMouse = false;
	}
	else if(event.button == SDL_BUTTON_WHEELUP)
	{
		m_CameraDistance -= 40 * dt;
	}
}

void MainGameState::OnDeactivated()
{
	TheEventPoller::Instance()->RemoveHandler(this);
}

MainGameState::~MainGameState()
{

}